package main

import "fmt"

//利用协程统计 素数
func main() {
	intChan := make(chan int, 80000)
	primeChan := make(chan int, 80000)
	exitChan := make(chan bool, 4)
	go putNum(intChan)
	//利用4个协程进行统计计算
	for i := 0; i < 8; i++ {
		go primeNum(intChan, primeChan, exitChan)
	}

	//匿名函数
	go func() {
		defer close(exitChan)
		defer close(primeChan)
		for i := 0; i < 8; i++ {
			<-exitChan
		}
	}()

	count := 1
	for {
		v, ok := <-primeChan
		if !ok {
			break
		}
		fmt.Printf("第%v个素数:%v \n", count, v)
		count++
	}

	fmt.Print("任务结束")

}

//putNum 往管道中放入待统计的数字
func putNum(intChan chan int) {
	defer close(intChan)
	for i := 1; i <= 200000; i++ {
		intChan <- i
	}
}

//primeNum 从intChan获取数字，若是素数则往primeChan存放
func primeNum(intChan chan int, primeChan chan int, exitChan chan bool) {
	for {
		v, ok := <-intChan
		if !ok {
			break
		}
		//判断是否是素数
		flag := true
		for i := 2; i < v; i++ {
			if v%i == 0 {
				flag = false
				break
			}
		}
		//如果是素数则放到素数管道中
		if flag {
			primeChan <- v
		}
	}
	//退出循环是因为intChan被关闭
	//因此当前计算任务结束
	//向退出管道写入数据
	//只有4个任务都完成，才可以关闭primeChan
	exitChan <- true
}
